package fractal.filter;

public abstract class TransferFilter extends FractalFilter
{
	protected int[] rTable, gTable, bTable;
	protected boolean initialized = false;
	protected boolean canFilterIndexColorModel = false;

	public TransferFilter()
	{
		canFilterIndexColorModel = true;
	}

	public int filterRGB(int x, int y, int rgb)
	{
		int a = rgb & 0xff000000;
		int r = (rgb >> 16) & 0xff;
		int g = (rgb >> 8) & 0xff;
		int b = rgb & 0xff;
		r = rTable[r];
		g = gTable[g];
		b = bTable[b];
		return a | (r << 16) | (g << 8) | b;
	}

	protected void initialize()
	{
		initialized = true;
		rTable = gTable = bTable = makeTable();
	}

	protected int[] makeTable()
	{
		int[] table = new int[256];
		for (int i = 0; i < 256; i++)
			table[i] = clamp((int) (255 * transferFunction(i / 255.0f)));
		return table;
	}

	@Override
	protected void initFilter()
	{
		if (!initialized)
			initialize();
	}

	@Override
	protected int calculatePixel(int i)
	{
		int rgb = inPixels[i];
		int a = rgb & 0xff000000;
		int r = (rgb >> 16) & 0xff;
		int g = (rgb >> 8) & 0xff;
		int b = rgb & 0xff;
		r = rTable[r];
		g = gTable[g];
		b = bTable[b];
		return a | (r << 16) | (g << 8) | b;
	}

	protected abstract float transferFunction(float v);

	public int[] getLUT()
	{
		if (!initialized)
			initialize();
		int[] lut = new int[256];
		for (int i = 0; i < 256; i++)
		{
			lut[i] = filterRGB(0, 0, (i << 24) | (i << 16) | (i << 8) | i);
		}
		return lut;
	}

}
